//-----------------------------------------基础类型
const count: number = 123
const teacherName = 'Dell'

//--------------------------------------------------------对象类型
{
  class Person {} //类
  const dell: Person = new Person() //new 一个类

  //对象
  const teacher: {
    name: string
    age: number
  } = {
    name: 'dell',
    age: 18,
  }
  //数组
  const numbers1: number[] = [1, 2, 3]

  // 函数
  const getTotal: () => number = () => {
    return 123
  }

  //接收的string 类型  返回 number 类型
  const func = (str: string): number => {
    return parseInt(str)
  }
}

// ---------------------------   类型注解  // 类型推断
{
  let count: number
  count = 123 //类型注解

  let countInfo = 123 //类型推断

  function getTotal(firstNumber: number, secondNumber: number) {
    return firstNumber + secondNumber
  }
  const total = getTotal(1, 2)
}

// ---------------------------  函数相关类型

{
  //   function demo(): void {
  //     console.log('void类型  没有返回值')
  //   }
  //   function eroorEmitter(): never {
  //     //  throw new Error()
  //     while (true) {}
  //     console.log('函数永远不可能执行到最后 -> 类似死循环')
  //   }

  function add({ name, age }: { name: number; age: number }) {
    return name + age
  }

  add({ name: 1, age: 2 })
}

//--------------------------- 基本类型写法
{
  interface Person {
    name: 'string'
  }

  const rawData = '{"name":"dell"}'
  const newData: Person = JSON.parse(rawData)
  //   console.log(typeof newData, 'newData ')

  let temp: number | string = 123
  temp = '123'
  //   console.log(temp)  string
}

//--------------------------- TS的数组
{
  //数组1
  const arr: (number | string)[] = [1, '2', 3]

  const stringArrr: string[] = ['1', '2', '3']

  const undefinedArr: undefined[] = [undefined]

  //   类型别名
  type User = { name: string; age: number }

  const objectArr: User[] = [
    {
      name: 'dell',
      age: 28,
    },
  ]

  //元组  tuple
  const tacherInfo: [string, string, number] = ['dell', 'male', 18]
}

////--------------------------- interface接口
// interface 是一个用来做语法校验的
{
  //  注意 type  类型别名 和 interface Person 接口  区别就是 interface 是一个对象  而别名是直接代表类型
  //   type Person1 = string
  interface Person {
    // readonly name:string  是代表  只能读取值 不能赋值
    name: string
    age?: number //age?   传参的时候可有可无
    [propName: string]: any //  propName其他属性   属性的值 any  可以任何类型值
    say(): string //say()方法  返回值类型 是string类型
  }

  const person = {
    name: 'dell',
    sex: 'male',
    say() {
      return '字符串'
    },
    teach() {
      return '字符串'
    },
  }

  const getPersonName = (person: Teacher): void => {
    //  console.log(person.name)
  }

  getPersonName(person)

  //calss 类 -> 去运用 interface接口
  class User implements Person {
    //注意 ： 类要去运用 interface 接口 必须具备 interface 的属性和类型
    name = 'string'
    say() {
      return '字符串'
    }
  }

  //interface - 接口继承
  interface Teacher extends Person {
    teach(): string
  }

  //interface  定义函数
  interface SayHi {
    //(传参: string): 返回string
    (word: string): string
  }

  const sty: SayHi = (word: string) => {
    return word
  }
}

////------------------------------------------------类的定义于继承
{
  // 1、继承跟JS的继承是一样
  // 2、重写后调用父类的方法  -> 就会用到 super
  class Person {
    name = 'dell'
    getName() {
      return this.name
    }
  }

  class Teacher extends Person {
    getTeacherName() {
      return 'Teac'
    }

    getName() {
      return super.getName() + 'lee'
    }
  }

  const teacher = new Teacher()
  //   console.log(teacher.getName(), 'teacher')
}

////------------------------------------------------ 类中的访问类型和构造器[ ]

// public  允许我在类的 内外被调用
// private 允许在类内被使用
// protected 允许在类内及继承的子类中使用

{
  // constructor构造器
  // 什么时候执行 ？  new 一个实例的时候 就会自动执行constructor
  class Person {
    //  传统写法
    //  public name: string
    //  constructor(name: string) {
    //    this.name = name
    //  }

    //  简写
    constructor(public name: string) {}
  }
  const name = 'name'
  const person = new Person(name)
  // console.log(person.name)
}

{
  class Person {
    constructor(public name: string) {}
  }

  class Teacher extends Person {
    constructor(public age: number) {
      super('name') //继承persor 类以后 要调用constructor构造器  就要用 super
    }
  }

  const person = new Teacher(18)
  // console.log(person.age, 'person')
}

//  -------------------------------------------- 静态属性，Setter和Getter([ ]

{
  //单例模式
  class Demo {
    //声明一个私有静态  instance 类型是 Demo
    private static instance: Demo
    private constructor(public name: string) {}
    static getInstance(name: string) {
      //判断是否有instance实例  没有则new  一个实例
      if (!this.instance) {
        this.instance = new Demo(name)
      }
      return this.instance
    }
  }

  const name = '字符串'
  const demo1 = Demo.getInstance(name)

  console.log(demo1, 'demo')
}

//  -------------------------------------------  抽象类
{
  // readonly 只读  不可取
  // 抽象类 只能被继承  不能被直接实例化
  // new Geom   错误
  abstract class Geom {
    // width: number
    getType() {
      return 'Geom'
    }

    abstract getArea(): number
  }

  class Circle extends Geom {
    getArea(): number {
      return 123
    }
  }
}

//interface  接口类
//接口的继承   要有同对象的属性 抽取出来 比如下面的name  抽取到Person 这个接口里
{
  interface Person {
    name: string
  }

  interface Teacher extends Person {
    name: string
    teacherAge: number
  }

  const getUserInfo = (user: Person) => {
    console.log(user.name)
  }

  const obj = {
    name: 'Teacher',
    teacherAge: 3,
  }

  getUserInfo(obj)
}
